package com.tutu.common.config;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.BeanPredicate;
import org.apache.commons.collections.ClosureUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ComparatorUtils;
import org.apache.commons.collections.PredicateUtils;
import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.tutu.common.GlobalConstants;
import com.tutu.sys.entity.SysMsgUser;
import com.tutu.sys.service.ISysMsgService;
import com.tutu.user.entity.SysMenuInfo;
import com.tutu.user.entity.SysUser;

public class AuthorityInterceptor extends HandlerInterceptorAdapter {

	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Resource
	private ISysMsgService sysMsgService;

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if(null!=authentication){
			Object object = authentication.getPrincipal();
			if(object instanceof SysUser){
				SysUser sysUser = (SysUser) object;
				if(!CollectionUtils.isEmpty(sysUser.getAuthorities())) {
					List<SysMenuInfo> sysMenuInfos = new ArrayList<SysMenuInfo>();
					boolean isActive = false;
					String menuId = null;
					String menuUrl = null;
					RequestMatcher requestMatcher = null;
					for(GrantedAuthority auth : sysUser.getAuthorities()){
						if(auth instanceof SysMenuInfo){
							SysMenuInfo sysMenuInfo = (SysMenuInfo) auth; 
							if(StringUtils.isNotBlank(sysMenuInfo.getMenuId())){
								sysMenuInfos.add(sysMenuInfo);
								menuUrl = sysMenuInfo.getMenuUrl().replace("?", "\\?") + "*";
								requestMatcher = new AntPathRequestMatcher(menuUrl, null);
								if(requestMatcher.matches(request)){
									isActive = true;
									menuId = sysMenuInfo.getMenuId();
								}
							}
						}
					}
					if(isActive){
//						初始化，默认不选中
						CollectionUtils.forAllDo(sysMenuInfos, ClosureUtils.invokerClosure("setIsActive", new Class[]{boolean.class}, new Object[]{false}));
						if(!StringUtils.equals("0", menuId)){
							setMenuActive(sysMenuInfos, menuId);
						}
						Collection<SysMenuInfo> menuInfos = convertMenu(sysMenuInfos);
						request.getSession().setAttribute(GlobalConstants.SESSION_USER_MENU, menuInfos);
					}else{
						if(null == request.getSession().getAttribute(GlobalConstants.SESSION_USER_MENU)){
							Collection<SysMenuInfo> menuInfos = convertMenu(sysMenuInfos);
							request.getSession().setAttribute(GlobalConstants.SESSION_USER_MENU, menuInfos);
						}
					}
				}
			}
		}
//		我的未读消息数
		int msgCount = 0;
		try{
			SysMsgUser sysMsgUser = new SysMsgUser();
			sysMsgUser.setAliveFlag(GlobalConstants.FLAG_ENABLE);
			sysMsgUser.setReceiver(GlobalConstants.getCurrentUser().getUserId());
			msgCount = this.sysMsgService.getMyMsgCount(sysMsgUser);
		}catch(Exception e){
			logger.error("获取我的未读消息数", e);
		}
		request.setAttribute("msgCount", msgCount);
		
		return super.preHandle(request, response, handler);
	}
	
	/**
	 * 转换菜单
	 * @param sysMenuInfos
	 */
	protected Collection<SysMenuInfo> convertMenu(Collection<SysMenuInfo> sysMenuInfos){
		if(CollectionUtils.isEmpty(sysMenuInfos))
			return null;
		Comparator<Long> comparator = ComparableComparator.getInstance();
		comparator = ComparatorUtils.nullHighComparator(comparator);
		ComparatorChain comparatorChain = new ComparatorChain(new BeanComparator<Long>("orderBy", comparator));
		comparatorChain.addComparator(new BeanComparator<String>("menuCode"));
		SortedSet<SysMenuInfo> sysMenuInfoSet = new TreeSet<SysMenuInfo>(comparatorChain);
		for(SysMenuInfo sysMenuInfo : sysMenuInfos){
			if(StringUtils.equals("0", sysMenuInfo.getParentId())){
				sysMenuInfoSet.add(sysMenuInfo);
				continue;
			}
			SysMenuInfo parentSysMenuInfo = (SysMenuInfo) CollectionUtils.find(sysMenuInfos, new BeanPredicate("menuId",PredicateUtils.equalPredicate(sysMenuInfo.getParentId())));
			if(null == parentSysMenuInfo){
				logger.error("菜单配置有误,没有父节点ID：【{}】的权限", sysMenuInfo.getParentId());
				continue;
			}
			if(CollectionUtils.isEmpty(parentSysMenuInfo.getSonSysMenuInfos())){
				parentSysMenuInfo.setSonSysMenuInfos(new TreeSet<SysMenuInfo>(comparatorChain));
			}
			parentSysMenuInfo.getSonSysMenuInfos().add(sysMenuInfo);
		}
		return sysMenuInfoSet;
	}
	
	protected void setMenuActive(Collection<SysMenuInfo> sysMenuInfos, String menuId){
		if(CollectionUtils.isEmpty(sysMenuInfos)&&StringUtils.isEmpty(menuId)){
			return;
		}
		SysMenuInfo sysMenuInfo = (SysMenuInfo) CollectionUtils.find(sysMenuInfos, new BeanPredicate("menuId", PredicateUtils.equalPredicate(menuId)));
		if(null != sysMenuInfo){
			sysMenuInfo.setIsActive(true);
			if(!StringUtils.equals("0", sysMenuInfo.getParentId())){
				setMenuActive(sysMenuInfos, sysMenuInfo.getParentId());
			}
		}
	}
}
